package com.fjec.market.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fjec.common.Const;
import com.fjec.common.enums.EnumSysCode;
import com.fjec.common.exception.BizException;
import com.fjec.common.protocol.JsonResult;
import com.fjec.common.shiro.AccountInfo;
import com.fjec.common.util.DateUtil;
import com.fjec.common.util.SpecialMapUtil;
import com.fjec.common.view.AnnexBizItem;
import com.fjec.market.entity.BizMarketBusi;
import com.fjec.market.entity.InfoFarmer;
import com.fjec.market.entity.InfoServiceProject;
import com.fjec.market.es.document.FarmerDocument;
import com.fjec.market.es.repository.FarmerRepository;
import com.fjec.market.feign.BaseClient;
import com.fjec.market.feign.UserClient;
import com.fjec.market.mapper.InfoFarmerMapper;
import com.fjec.market.rabbitmq.provider.ShopNumProvider;
import com.fjec.market.service.IBizMarketBusiService;
import com.fjec.market.service.IInfoFarmerService;
import com.fjec.market.service.IInfoPersonalService;
import com.fjec.market.service.IInfoServiceProjectService;
import org.apache.commons.collections.MapUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.sound.sampled.Line;
import java.time.LocalDate;
import java.util.*;

/**
 * <p>
 * 004.果农表 服务实现类
 * </p>
 *
 * @author admin
 * @since 2020-09-07
 */
@Service
@Transactional
public class InfoFarmerServiceImpl extends ServiceImpl<InfoFarmerMapper, InfoFarmer> implements IInfoFarmerService {

    @Resource
    private InfoFarmerMapper mapper;

    @Resource
    private FarmerRepository farmerRepository;

    @Resource
    private IBizMarketBusiService bizMarketBusiService;

    @Resource
    private UserClient userClient;

    @Autowired
    private BaseClient baseClient;

    @Autowired
    private RedisTemplate redisTemplate;

    @Resource
    private ShopNumProvider shopNumProvider;

    @Resource
    private IInfoPersonalService personalService;

    @Resource
    private IInfoServiceProjectService infoServiceProjectService;

    @Override
    public JsonResult getFarmerByUserId(Long userId) {
        Map<String, Object> result = mapper.getFarmerWithMarkCodeByUserId(userId);
        if (result == null)
            return JsonResult.SUCCESS;
        result = SpecialMapUtil.lowKey(result);
        result.put("markCode", Integer.valueOf(String.valueOf(result.get("markCode"))));
        String shopNum = MapUtils.getString(result, "shopNum");
        String shopNumStr = shopNum.substring(0, 2) + "-" + shopNum.substring(2);
        result.put("shopNum", shopNumStr);
        return JsonResult.success().data(result).build();
    }

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public JsonResult saveFarmer(InfoFarmer farmer, String markCode, Long picId, Object verifyCode) {
        if (farmer.getId() == null) {
            String phone = farmer.getPhone();
            // check verify code
            String cachedVerifyCodeKey = Const.FJEC_SMS_VERIFY_CODE_KEY + phone;
            Object cachedVerifyCode = redisTemplate.opsForValue().get(cachedVerifyCodeKey);
            if (verifyCode == null || !Objects.equals(cachedVerifyCode, verifyCode)) {
                return JsonResult.failure()
                        .code(EnumSysCode.ERR_3009.getCode())
                        .message(EnumSysCode.ERR_3009.getMsg())
                        .build();
            }
            // check phone exists
            if (userClient.existsPhone(phone)) {
                return JsonResult.failure()
                        .code(EnumSysCode.ERR_3014.getCode())
                        .message(EnumSysCode.ERR_3014.getMsg())
                        .build();
            }
            // 已经注册过的用户不允许再注册
            if (AccountInfo.getBusiType() != 1)
                return JsonResult.failure()
                        .code(EnumSysCode.ERR_3013.getCode())
                        .message(EnumSysCode.ERR_3013.getMsg())
                        .build();

            // 检查店铺名是否存在
            String name = farmer.getShopName();
            int exist = this.count(new QueryWrapper<InfoFarmer>().eq("ShopName", name));
            if (exist != 0) {
                return JsonResult.failure()
                        .code(EnumSysCode.ERR_3011.getCode())
                        .message(EnumSysCode.ERR_3011.getMsg())
                        .build();
            }
            // save farmer
            farmer.setShopNum(0L);
            farmer.setDepoStatus(0);
            farmer.setShopStar(0);
            farmer.setWeight(0);
            farmer.setRealNameAuth(0);
            farmer.setHasSaleable(0);
            farmer.setAllowPhone(1);
            farmer.setRegStatus(1);
            farmer.setCreateTime(DateUtil.nowLdt());
            try {
                this.save(farmer);
            } catch (DuplicateKeyException e) {
                throw new BizException(EnumSysCode.ERR_3011.getCode(), EnumSysCode.ERR_3011.getMsg());
            }

            //农户只能属于一个市场
            BizMarketBusi bizMarketBusi = new BizMarketBusi();
            bizMarketBusi.setBusiType(2);
            bizMarketBusi.setMarkCode(Integer.valueOf(markCode));
            bizMarketBusi.setBusiId(farmer.getId());
            bizMarketBusi.setPaidRent(0);
            bizMarketBusiService.save(bizMarketBusi);
            // 更新InfoPersonal busiType用于统计
            personalService.updateBusiTypeByUserId(farmer.getUserId(), 2);
            // save to es
            farmerRepository.save(new FarmerDocument(farmer.getId(), AccountInfo.getUserId(), farmer.getShopName()));
            // RPC更新用户信息
            Map<String, Object> dataMap = new HashMap<>();
            dataMap.put("userId", farmer.getUserId());
            dataMap.put("roleCode", "Farmer");
            dataMap.put("phone", phone);
            int result = userClient.updateUserInfoForCreateShop(dataMap);
            if (result == -1) {
                throw new BizException(EnumSysCode.FAILURE.getCode(), EnumSysCode.FAILURE.getMsg());
            } else if (result == 3014) {
                throw new BizException(EnumSysCode.ERR_3014.getCode(), EnumSysCode.ERR_3014.getMsg());
            }
            // send to mq for generate shopNum
            shopNumProvider.sendShopNumGen(2, farmer.getId(), Integer.valueOf(markCode));
            // delete verify code from redis
            redisTemplate.delete(cachedVerifyCodeKey);
            return JsonResult.SUCCESS;
        } else {
            farmer.setRegStatus(2);
            this.updateById(farmer);
            // rpc set annex enable
            if (picId != null && picId != 0L) {
                List<AnnexBizItem> annexBizItems = new ArrayList<>();
                AnnexBizItem bizItem = new AnnexBizItem();
                bizItem.setAnnexId(picId);
                bizItem.setBizId(farmer.getId());
                bizItem.setBizType(2);
                annexBizItems.add(bizItem);
                baseClient.enableAnnexStatus(annexBizItems);
            }
            return JsonResult.SUCCESS;
        }
    }

    @Override
    public List<InfoFarmer> getFarmerByMarkCode(Integer markCode, Page page) {
        List<InfoFarmer> farmers = mapper.getFarmerByMarkCode(markCode, page);
        // 暂时随机排序
//        farmers.forEach(farmer -> {
//            if (farmer.getDepoStatus() == 0) farmer.setWeight(farmer.getWeight() - 10000);
//            if (farmer.getHasSaleable() == 0 ) farmer.setWeight(farmer.getWeight() - 1000);
//        });
//
//        farmers.sort(Comparator.comparing(InfoFarmer::getWeight));
        return farmers;
    }

    @Override
    public Map<String, Object> getFarmerDepoStatusByUserId(Long userId) {
        return mapper.getFarmerDepoStatusByUserId(userId);
    }

    @Override
    public Map<String, Object> getBusinessDepoStatusByUserId(Long userId) {
        return mapper.getBusinessDepoStatusByUserId(userId);
    }

    @Override
    public List<InfoFarmer> getFarmersByFarmerIdsAndMarkCode(int markCode, List<Long> farmerIds, Page page) {
        return mapper.getFarmersByFarmerIdsAndMarkCode(markCode, farmerIds, page);
    }

    @Override
    public JsonResult getDepositInfo() {
        Long userId = AccountInfo.getUserId();
        QueryWrapper<InfoFarmer> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("userId", userId);
        InfoFarmer entity = mapper.selectOne(queryWrapper);
        Map<String, Object> view = new HashMap<>();
        view.put("depoStatus", entity.getDepoStatus());
        view.put("deposit", entity.getDeposit());
        view.put("depoPaymTime", entity.getDepoPaymTime());
        view.put("depoApplyBackTime", entity.getDepoApplyBackTime());
        view.put("depoRefundTime", entity.getDepoRefundTime());
        InfoServiceProject serviceProject = infoServiceProjectService.getOne(new QueryWrapper<InfoServiceProject>().eq("ServCode", "depo2"));
        view.put("amount", serviceProject.getAmount() / 100);
        return JsonResult.success()
                .data(view)
                .build();
    }

    @Override
    public List<InfoFarmer> getFarmerByShopNumAndMarkCode(int markCode, Long shopNum) {
        return mapper.getFarmerByShopNumAndMarkCode(markCode, shopNum);
    }

    @Override
    public List<Map<String, Object>> getFarmerForShopNumGen(Integer limit, Integer minutes) {
        return mapper.getFarmerForShopNumGen(limit, minutes);
    }
}
